// Copyright (c) 2020 Presto Labs Pte. Ltd.
// Author: daniel

#pragma once

#include <functional>

#include <boost/asio/io_context.hpp>
#include <glog/logging.h>

namespace FIX {
class Message;
}

namespace coin2::exchange::base::order {
class BaseOrderProcessor;
struct OrderExecution;
}  // namespace coin2::exchange::base::order

namespace coin2::exchange::base::market {
struct MarketExchangeApi;
}

namespace coin2::exchange::base::symbology {
class IProduct;
class IProductHolder;
}  // namespace coin2::exchange::base::symbology

namespace coin2::exchange::base::executor {
class CoinReactor;
}  // namespace coin2::exchange::base::executor

namespace coin2::exchange::base::api_base::fix {

/********************************************************************************
 * interface class IFixTradeClient                                              *
 ********************************************************************************/
class IFixTradeClient {
 public:
  using Processor = coin2::exchange::base::order::BaseOrderProcessor;
  using OrderExecution = coin2::exchange::base::order::OrderExecution;
  using Executor = boost::asio::io_context;
  using SubscriberCB = std::function<void(const FIX::Message&)>;
  using IProduct = coin2::exchange::base::symbology::IProduct;
  using IProductHolder = coin2::exchange::base::symbology::IProductHolder;
  using GetProductHolderFunc =
      std::function<const IProductHolder*(const IProduct& product, int64_t timestamp)>;

  virtual ~IFixTradeClient() = default;
  virtual void Start() = 0;
  virtual void Stop() = 0;
  virtual bool IsAvailable() const = 0;
  virtual void SetExecutor(Executor*) = 0;
  virtual void SetMainReactor(executor::CoinReactor&) {
    LOG(WARNING) << "SetMainReactor Not implemented";
  }
  virtual void SetProcessor(Processor*) = 0;
  virtual void SetGetProductHolder(GetProductHolderFunc) = 0;
  virtual void AddSubscriber(SubscriberCB) = 0;
  virtual void PlaceOrder(const OrderExecution&) = 0;
  virtual void CancelOrder(const OrderExecution&) = 0;
  virtual void CancelOrderAll(const OrderExecution&) {
    CHECK(false) << "TODO(daniel): to implement";
  }
  virtual void QueryOrder(const OrderExecution&) = 0;
  virtual void AmendOrder(const OrderExecution&) {
    // TODO(daniel):
    CHECK(false) << "AmendOrder is not implemented";
  }
};

}  // namespace coin2::exchange::base::api_base::fix
